﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System.Drawing.Design;

namespace ProgNetComponents.Design.Editors
{
    /// <summary>
    /// Gets edito allowing to pick some items from list using checkboxex
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseCheckedListEditor<T> : UITypeEditor
    {
        /// <summary>
        /// IWindowsFormsEditorService
        /// </summary>
        protected IWindowsFormsEditorService editorService;
        /// <summary>
        /// Dictionary of items
        /// </summary>
        protected Dictionary<string, T> list;
        /// <summary>
        /// IServiceProvider
        /// </summary>
        protected IServiceProvider servideProvider;
        /// <summary>
        /// ITypeDescriptorContext
        /// </summary>
        protected System.ComponentModel.ITypeDescriptorContext context;
        /// <summary>
        /// ListBox control
        /// </summary>
        protected CheckedListBox listBox;
        /// <summary>
        /// Gets if dropdown can be resized
        /// </summary>
        public override bool IsDropDownResizable
        {
            get
            {
                return true;
            }
        }
        /// <summary>
        /// Creates ListBox
        /// </summary>
        protected virtual void CreateListBox()
        {
            if (listBox == null)
            {
                listBox = new CheckedListBox();
                listBox.BorderStyle = BorderStyle.None;
                listBox.KeyDown += new KeyEventHandler(listBox_KeyDown);
                //listBox.MouseDown += new MouseEventHandler(listBox_MouseDown);
            }
            list = GetListBoxItems();
            listBox.Items.Clear();
            foreach (string key in list.Keys)
                listBox.Items.Add(key);
        }
        private object _Owner;
        /// <summary>
        /// Owner
        /// </summary>
        protected object Owner
        {
            get { return _Owner; }
        }
        /// <summary>
        /// Closes dropdown
        /// </summary>
        protected void CloseDropDown()
        {
            if (editorService != null)
                editorService.CloseDropDown();
        }

        private void listBox_MouseDown(object sender, MouseEventArgs e)
        {
            CloseDropDown();
        }

        private void listBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                CloseDropDown();
        }
        /// <summary>
        /// Edits value
        /// </summary>
        /// <param name="context"></param>
        /// <param name="provider"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            this.context = context;
            _Owner = context.Instance;
            servideProvider = provider;
            editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            if (editorService != null)
            {
                T[] tab = value as T[];

                CreateListBox();
                List<string> l = new List<string>();
                if (tab != null)
                {
                    foreach (T t in tab)
                    {
                        string key = GetKeyForValue(t);
                        if (!l.Contains(key))
                            l.Add(key);
                    }
                    for (int i = 0; i < listBox.Items.Count; i++)
                    {
                        if (l.Contains(listBox.Items[i].ToString()))
                            listBox.SetItemChecked(i, true);
                    }
                }
                editorService.DropDownControl(listBox);
                List<T> l2 = new List<T>();
                foreach (object o in listBox.CheckedItems)
                {
                    if (list.ContainsKey(o.AsString()))
                        l2.Add(list[o.AsString()]);
                }

                return l2.ToArray();
            }
            return null;
        }
        /// <summary>
        /// Gets UITypeEditorEditStyle
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }
        /// <summary>
        /// Gets dictionaty of items
        /// </summary>
        /// <returns></returns>
        protected abstract Dictionary<string, T> GetListBoxItems();
        /// <summary>
        /// Gets key for specified value
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected virtual string GetKeyForValue(T value)
        {
            if(list!=null)
            foreach(KeyValuePair<string, T> kvp in list){
                if (value == null)
                {
                    if (kvp.Value == null)
                        return kvp.Key;
                }
                else if (value.Equals(kvp.Value))
                    return kvp.Key;
            }
            return null;
        }
    }
}
